
What is a sprite?
Sprites are graphical objects visible on
the computer screen. Most sprites are also
moving objects. Sprites are useful in the
implementation of active imagemaps, puzzles,
simulations, and games, among other possibilities.
Sprites are aware of collisions with other sprites,
as well as interactions with the mouse, the keyboard,
and the edges of the playfield. Sprites always reside in
playfields, which
must be constructed first.
Other capabilities of sprites
Baklava sprites can be told what direction to move in
and how fast to travel (in pixels per second), without
further intervention from the programmer, until something
"interesting" such as a collision takes place.
In addition, each sprite knows what "level" it is on.
Sprites at higher levels are drawn on top. This allows
"foreground" sprites to move across "background" sprites.
It is also possible to specify that certain sprites
never collide with others.
If the setImage method is used
to assign an image that was loaded from a transparent GIF,
then baklava will take this into account in determining
collisions. This allows non-rectangular sprites to
interact gracefully.
Extending Sprites: Yes, You Will Need To
To do truly interesting things with sprites, you will
need to "subclass" them. This allows you to write your
own class that has all of the built-in behavior of a
sprite, plus the additional "smarts" necessary
for your own application.
Receiving Events: Pick Up the Courtesy Phone...
Methods such as collisionWith, which
do nothing in the "raw" Sprite class, are invoked
by the playfield to let you know when one sprite
collides with another sprite or with the edges of
the playfield. You can replace these methods with
useful versions in your subclass of Sprite.
Also, The very important
timer method is invoked when a timer set
by a call to setTimer
or setTimerAll expires.
Replace this method to carry out particular actions at
particular times, or when notified by another sprite.
Other events that are reported to sprites are
normally handled well by the built-in sprite code, but you can
add additional behavior. Methods such as onStep and
onGoodbye can optionally be replaced
to move in more complex ways, or to carry out extra steps when
a sprite is removed from a playfield.
About Sprites and Threads...
Implementing a separate thread for each sprite is not
recommended. Instead, subclass the Sprite class to respond to various
events, and use the setTimer method to carry
out particular actions at particular times. Baklava takes
great care to deliver timers in the correct order and to
synchronize the delivery of timers and events in a safe
and reliable manner.
Example: Shy Sprites
This applet contains a group of sprites which are
uncomfortable with each other, and with you, for that
matter. When they come in contact with one another
or the mouse, they change direction and run away quickly.
This is done by subclassing Sprite to add new versions
of the collisionWith and
mouseEnter methods.
import baklava.*;
// A private class implementing the shy sprites.
class Shy extends Sprite {
// A timer ID we'll use later. "final" so java
// will know it's just a constant and not
// reserve any real space for it.
final int timerSlowDown = 0;
public Shy(Playfield p, Image image)
{
// Call the Sprite constructor. This is required.
super(p);
// Now set the image.
setImage(image);
// Pick a random location safely inside the playfield.
// Math.random() returns a value between 0 and 1.
int x = (int) (Math.random() * (p.getWidth() - getWidth()));
int y = (int) (Math.random() * (p.getHeight() - getHeight()));
// Set the location.
setX(x);
setY(y);
// Set a direction.
setDirection((int) (Math.random() * 360));
// Set a speed.
setSpeed(30);
// Just bounce at the edges of the playfield.
setEdgeHandling(edgeBounce);
}
void collisionWith(Sprite s)
{
// We collided with something. Run awaaay!
// Find the direction to the thing we collided with.
int direction = getPlayfield().angleOfVector(
getX(), getY(), s.getX(), s.getY());
// Now go the other way...
direction += 180;
setDirection(direction);
// And speed up
setSpeed(60);
// Set a timer to slow down after 2 seconds.
setTimer(2000, timerSlowDown);
}
void mouseEnter(Event evt, int x, int y)
{
// The mouse entered the sprite. Run away.
setDirection((int) (Math.random() * 360));
setSpeed(60);
// Set a timer to slow down after 2 seconds.
setTimer(2000, timerSlowDown);
}
void timer(int timerId)
{
if (timerId == timerSlowDown) {
// Relax.
setSpeed(30);
}
}
}
public class ShyApplet extends Applet {
Playfield p;
// CHANGE THIS, of course, to a directory where you keep
// suitable GIFs.
String base = "http://www.mysite.com/graphics/";
public void init() {
// Use no layout manager
setLayout(null);
// Create the playfield
p = new Playfield(this, bounds().width, bounds().height);
// Fetch an image
Image wanderer = p.getImage(base + "wanderer.gif");
// Construct the Shy objects.
int i;
for (i = 0; (i < 5); i++) {
new Shy(p, wanderer);
}
// Now start movement in the playfield
p.start();
// Now display the playfield
add(p);
}
public void stop() {
p.suspend();
}
public void start() {
p.resume();
}
public void destroy() {
p.stop();
}
};
baklava.Sprite Method Reference
This section provides a reference guide to the publicly accessible
methods (functions) available in the baklava.Sprite class.
- Sprite(Playfield playfieldArg)
- This is the constructor method. The constructor accepts
a playfield as an argument. You must
construct a playfield first before constructing a sprite. If you
subclass Sprite, which is very common, you will need to invoke
this constructor at the start of your subclass constructor.
Example:
class Tree extends Sprite {
Tree(Playfield p, int x, int y) {
// Call the Sprite constructor
super(p);
// Now do other things...
}
}
- final void goodbye()
- The goodbye method should be invoked when a sprite is
no longer wanted. In response, baklava will call the
onGoodbye method, and then release
various resources associated with the sprite. Note that goodbye
itself cannot be replaced by a subclass of sprite, but
onGoodbye is provied for this purpose.
- void onGoodbye()
- The onGoodbye method is invoked by baklava
when the goodbye method is
invoked, and before the resources associated with the
sprite are released. The default implementation of
onGoodbye does nothing. This method is provided as
an event "hook" for the programmer to replace in
subclasses of sprite. For instance, you might wish to
invoke the goodbye method on other sprites associated
with this sprite.
- final void setSpeed(int s)
- The setSpeed method sets the speed of movement of the
sprite, in pixels per second. Together with the
setDirection,
setDirectionToward
and setTarget
methods, this provides a simple way to animate sprites
without a great deal of effort on your part.
- final int getSpeed(int s)
- The getSpeed method returns the speed of movement
of the sprite, in pixels per second.
- final void setLevel(int l)
- It is often desirable for one sprite to be thought
of as "on top" of another. For example, many applets include
one "background" sprite which should appear beneath
the rest. In baklava, this is accomplished by calling
the setLevel method to indicate the "stacking order"
of the sprites. The greater the value of
l
, the
higher the sprite appears in the stacking order. By default,
all sprites have a level of zero (0), so a background
can be created by invoking setLevel on a large sprite
with a level of -1. To greatly improve performance,
it is also important to
call setBackground on sprites
that are considered to be part of the background.
- final int getLevel()
- The getLevel method returns the "level" of this
sprite in the stacking order. The highest-numbered
sprites appear on top when sprites overlap.
- final void setX(int x)
- The setX method sets the location of the sprite
on the X axis, in pixels measured from left to right.
The leftmost pixel is at coordinate zero (0).
- final int getX()
- The getX method returns the location of the sprite
on the X axis, in pixels measured from left to right.
The leftmost pixel is at coordinate zero (0).
- final void setY(int x)
- The setY method sets the location of the sprite
on the Y axis, in pixels measured from top to bottom.
The topmost pixel is at coordinate zero (0).
- final int getY()
- The getY method returns the location of the sprite
on the Y axis, in pixels measured from top to bottom.
The topmost pixel is at coordinate zero (0).
- final void setTile(Image image, int w, int h)
- The setTile method sets a new appearance for the sprite.
The sprite will be of the size indicated by the w (width)
and h (height) arguments, and the image will be "tiled"
over and over throughout the sprite. For an easy way to
fetch images via the web, see the
Playfield.getImage method.
The use of that method is strongly recommended.
setTile is commonly used to create background sprites; for more on
creating backgrounds, see the setBackground
and setLevel methods.
- final void setImage(Image image)
- The setImage method sets a new appearance for the sprite.
The size of the sprite will match the size of the image.
For an easy way to
fetch images via the web, see the
Playfield.getImage method.
The use of that method is strongly recommended.
- final Image getImage()
- The getImage method returns the current image being
displayed by the sprite. Note that if the image was set
using the setTile method, the image returned by getImage will
be a large image containing many repetitions of the original tile,
rather than just not just the tile.
- final void setWidth(int w)
- The setWidth method sets the width of the sprite,
in pixels. This is most useful when the programmer
also replaces the paint method
to draw something other than or in addition to
an ordinary image. Note that the width will be changed
again if the setImage method
is called later.
- final int getWidth()
- The getWidth method returns the width of the sprite, in pixels.
The value returned by this method is not meaningful until
setImage or setTile
has been called.
- final void setHeight(int h)
- The setHeight method sets the height of the sprite,
in pixels. This is most useful when the programmer
also replaces the paint method
to draw something other than or in addition to
an ordinary image. Note that the height will be changed
again if the setImage method
is called later.
- final int getHeight()
- The getHeight method returns the height of the sprite, in pixels.
The value returned by this method is not meaningful until
setImage or setTile
has been called.
- final void setDirection(int direction)
- The setDirection method sets the direction (angle), in degrees, in
which the sprite will move. Acceptable values range from 0 to 360.
Larger values are rounded down by dividing by 360 and taking
the remainder. Zero degrees points directly to the right.
Note that, because the Y axis ranges
from top to bottom, 90 degrees points straight down.
See also setDirectionToward
for a way to aim the sprite toward a specific point or object,
setTarget for a way to send an
sprite toward a specific point and stop moving when it arrives,
and setSpeed for a way to set the
sprite in motion. Sprite motion does not actually begin
until the Playfield.start
method has been invoked.
- final void setDirectionToward(int x, int y) OR final void setDirectionToward(Sprite s)
- The setDirectionToward method computes the angle from the
sprite's current location to the point in the playfield or other sprite
indicated, and sets the sprite's direction of movement to match
that angle. See also setTarget for a way
to "aim" a sprite toward a specific point and stop moving when
it arrives, and setSpeed for a way to set the
sprite in motion. Sprite motion does not actually begin
until the Playfield.start
method has been invoked.
- final void setTarget(int x, int y)
- The setTarget method computes the angle from the
sprite's current location to the point indicated,
and sets the sprite's direction of movement to match
that angle. When the sprite arrives at the target,
it automatically stops moving, and the
onArrival method is called.
See also setDirectionToward for a way
to "aim" a sprite toward a specific point or sprite without automatically
stopping upon arrival, and setSpeed for a way to
set the sprite in motion. Sprite motion does not actually begin
until the Playfield.start
method has been invoked.
- public void onArrival()
- The onArrival method is called when a sprite has arrived
at a target point set with the setTarget
method. By default, this method does nothing. Provide
your own version in your subclass of sprite to carry out interesting
actions when sprites arrive at their destinations.
- final int getDirection()
- The getDirection method returns the direction, in degrees, in
which the sprite is currently moving.
- void setEdgeHandling(int edgeHandlingArg)
- The setEdgeHandling method determines how the sprite should behave
when it contacts the edge of the playfield. Several simple
behaviors are available. If the argument to setEdgeHandling
is
Sprite.edgeSolid
, sprites will simply stop moving
at the edge of the playfield. If the argument is set to
Sprite.edgeBounce
, sprites will rebound off the edge
of the playfield. If the argument is set to Sprite.edgeWrap
,
sprites will pass through the edge of the playfield and reappear
on the far side. Solid edges are the default. To implement other
behaviors at the edge, replace the
collisionEdge method
with a new implementation in a subclass of Sprite.
- void mouseDown(Event evt, int x, int y)
- The mouseDown method is invoked by the playfield when a
mouse button is pressed down within this sprite. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.mouseDown method of the playfield by the
Java window toolkit.
- void mouseUp(Event evt, int x, int y)
- The mouseUp method is invoked by the playfield when a
mouse button is released within this sprite. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.mouseUp method of the playfield by the
Java window toolkit.
- void mouseMove(Event evt, int x, int y)
- The mouseMove method is invoked by the playfield when
the mouse is moved within this sprite. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.mouseMove method of the playfield by the
Java window toolkit.
- void mouseMove(Event evt, int x, int y)
- The mouseMove method is invoked by the playfield when
the mouse is moved within this sprite. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.mouseMove method of the playfield by the
Java window toolkit.
- void mouseDrag(Event evt, int x, int y)
- The mouseDrag method is invoked by the playfield when
the mouse is dragged (moved with a mouse button down) within this
sprite. The x and y arguments are relative to the upper left corner of
the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.mouseDrag method of the playfield by the
Java window toolkit.
- void mouseEnter(Event evt, int x, int y)
- The mouseEnter method is invoked by the playfield when
the mouse enters this specific sprite. The x and y arguments are relative
to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
Since sprites are not
considered to be windows by the Java window toolkit itself, the event
argument is that which was passed to the java.awt.Component.mouseMove
(not mouseEnter) method of the playfield.
- void mouseExit(Event evt, int x, int y)
- The mouseExit method is invoked by the playfield when
the mouse enters this specific sprite. The x and y arguments are relative
to the upper left corner of the sprite.
By default, this method does nothing. To react to the mouse,
replace this method in your subclass of sprite.
Since sprites are not
considered to be windows by the Java window toolkit itself, the event
argument is that which was passed to the java.awt.Component.mouseMove
(not mouseExit) method of the playfield.
- void keyDown(Event evt, int key)
- The keyDown method is invoked by the playfield when a
key is pressed down anywhere in the playfield. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the keyboard,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.keyDown method of the playfield by the
Java window toolkit. Note that, for consistency with the AWT,
the
key
argument is an integer, not a char.
You can compare it to a character by casting it to a char. Example:
// ... Inside a subclass of Sprite ...
public void keyDown(Event evt, int key)
{
if (((char) key) == ' ') {
// Dismiss this sprite when the space bar is pressed
goodbye();
}
}
- void keyUp(Event evt, int key)
- The keyUp method is invoked by the playfield when a
key is released anywhere in the playfield. The x and y
arguments are relative to the upper left corner of the sprite.
By default, this method does nothing. To react to the keyboard,
replace this method in your subclass of sprite.
The event argument is identical to the event passed to the
java.awt.Component.keyUp method of the playfield by the
Java window toolkit. Note that, for consistency with the AWT,
the
key
argument is an integer, not a char.
You can compare it to a character by casting it to a char. Example:
// ... Inside a subclass of Sprite ...
public void keyUp(Event evt, int key)
{
if (((char) key) == ' ') {
// Dismiss this sprite when the space bar is released
goodbye();
}
}
- void collisionEdge(int edge)
- The collisionEdge method is invoked by the playfield
when the sprite collides with one of the four edges of the
playfield. By default, collisionEdge carries out
the behavior set by the setEdgeHandling
method. If you need behavior that method cannot provide,
replace collisionEdge in your subclass of sprite.
The edge argument will be set to Sprite.edgeTop, Sprite.edgeBottom,
Sprite.edgeLeft, or Sprite.edgeRight.
- void collisionWith(Sprite s)
- The collisionWith method is invoked by the playfield
when a sprite collides with another sprite. The method is
invoked in both directions; that is, when sprites a and b
collide, both a.collisionWith(b) and b.collisionWith(a)
will be called by the playfield. Collisions take transparent
pixels into account if the sprite's image was loaded from
a transparent GIF; this allows non-rectangular objects
to behave in a realistic way. By default, this
method does nothing. Replace it in a subclass of sprite
in order to react to collisions. Note that,
if you use several subclasses of sprite,
Java's Object.getClass() and Class.forName() methods
become very useful in determining what type of sprite
has collided with this sprite. Example:
// ... inside a subclass of sprite ...
public void collisionWith(Sprite s)
{
if (s.getClass() == Class.forName("Scone")) {
// Let that scone know it's been hit.
// We know this object is a Scone, so
// we can now safely cast its type.
Scone scone = (Scone) s;
scone.hit();
}
}
- void onStep(int elapsed)
- Normally, baklava moves sprites according to their
direction (as set by setDirection)
and their speed (as set by setSpeed).
Occasionally, the programmer moves a sprite more abruptly
using the setX and setY
methods. However, there are times when these methods are
not sufficient. If your sprite has very complex behavior,
you may wish to replace the onStep method in your subclass of
sprite in order to move the sprite independently at every step in
baklava's simulation of sprite movement. The
elapsed
argument indicates how many milliseconds (thousandths of a second)
of time have elapsed since the previous step in the simulation;
this argument varies considerably. In most cases, it
is preferable to use the setDirection,
setDirectionToward,
and setSpeed methods for
movement, and the setTimer method
for special actions at specific times.
- void paint(Graphics g)
- Normally, baklava will paint sprites in the
playfield for you, displaying the appropriate image
as requested using the setImage
and setTile methods. In unusual
cases, you may wish to override this behavior and paint
the sprite yourself, by replacing the paint method
in a subclass of Sprite. If you want to draw
additional information in addition to the normal
sprite image, be sure to call the superclass
version of the paint method from your replacement,
as shown in the following example:
// ... in a subclass of Sprite ...
public void paint(Graphics g)
{
// First call the original paint method of Sprite
// to paint the image.
super.paint(g);
// Now draw a blue rectangle around the image
// if a flag is set.
if (highlighted) {
g.setColor(java.awt.Color.blue);
// NOTE: coordinates are relative to the playfield,
// not the sprite!
g.drawRectangle(getX(), getY(), getWidth(), getHeight());
}
}
- void setTimer(int delay, int id)
- This method is used to set a timer. After
delay
milliseconds (thousandths of a second), the timer
method will be invoked with the same id
argument.
This mechanism is the best way to carry out specific actions
at specific times. Also, settimg timers with a delay of zero
on other sprites is a useful way to communicate between
sprites. See also Playfield.setTimerAll
for a way to set a timer for all sprites, or for all sprites of
a specific subclass. See
Playfield.setGlobalTimer
for a way to set a "global" timer that is not associated
with a particular sprite.
- void timer(int id)
- This method is invoked by the playfield when a timer
set for this sprite has expired. By default,
this method does nothing. Replace this method in your
subclass of Sprite to respond to timers. Timers
are an important part of the baklava system and are very
useful as a way to carry out events at particular times,
as well as to communicate between sprites. See the
setTimer,
Playfield.setTimerAll
and Playfield.setGlobalTimer
methods for more information on this subject.
- final boolean getBackground()
- This method returns true if the background flag is set,
false otherwise. "Background" sprites use fewer resources,
and never collide with other objects or receive events
such as mouseDown and keyDown.
- final void setBackground(boolean flag)
- This method sets the background flag for this sprite.
"Background" sprites use fewer resources,
and never collide with other objects or receive events
such as mouseDown and keyDown.
For best results, be sure to call the setBackground method
before calling setImage or
setTile.
- final boolean getRectangular()
- This method returns true if the rectangular flag is set,
false otherwise. "Rectangular" sprites use fewer resources,
and are considered perfect rectangles for the purpose of
determining collisions. (Sprites without an image are
always considered rectangular.)
- final void setRectangular(boolean flag)
- This method sets the rectangular flag for this sprite.
"Rectangular" sprites use fewer resources,
and are considered perfect rectangles for the purpose of
determining collisions.
For best results, be sure to call the setRectangular method
before calling setImage or
setTile.
(Sprites without an image are
always considered rectangular.)
Up to Index
Copyright 1996 by Boutell.Com, Inc.